import { any } from "../../../core/logic";
import { Engine } from "../../../Engine";
import { Pass } from "../Pass";
import { Effect, EffectType } from "./Effect";
import { gtao_vert } from "./shaders/gtao_vert";
import { gtao_frag } from "./shaders/gtao_frag";
import { GTAOComputer } from "../compute/GTAOComputer";
/**
 * 全局阴影，提升场景的阴暗明亮对比度。
 * @class
 * @memberof w.effects
 */
class GTAO extends Effect {
  /**
   * @constructor
   * @param {*} opts
   * @param {Number} opts.maxDistance 三维平面内周围半径范围。
   * @param {Number} opts.maxPixel 二位平面内周围最大范围
   * @param {Number} opts.darkFactor 黑色因子
   */
  constructor(opts = {}) {
    super(opts);
    this.type=EffectType.GTAO;
    this.sampler = Engine.instance.device.createSampler({
      magFilter: "linear", //nearest linear
      minFilter: "linear",
    });
    this.gtaoComputer= new GTAOComputer(opts)
    this.addCompute(this.gtaoComputer)
    this.initPipeLine();
    this.maxDistance = any(opts.maxDistance, 50);
    this.maxPixel = any(opts.maxPixel, 50);
    this.darkFactor = any(opts.darkFactor, 1.2);
    this.rayMarchSegment = any(opts.rayMarchSegment, 6);
    this.multiBounce = any(opts.multiBounce, false);
    this.blendColor = any(opts.blendColor, true);
  }
  set maxDistance(v) {
    this._maxDistance = v;
    this.gtaoComputer.maxDistance=v
    return this;
  }
  get maxDistance() {
    return this._maxDistance;
  }
  set maxPixel(v) {
    this._maxPixel = v;
    this.gtaoComputer.maxPixel=v
    return this;
  }
  get maxPixel() {
    return this._maxPixel;
  }
  set darkFactor(v) {
    this._darkFactor = v;
    this.gtaoComputer.darkFactor=v
    return this;
  }
  get darkFactor() {
    return this._darkFactor;
  }
  set rayMarchSegment(v) {
    this._rayMarchSegment = v;
    this.gtaoComputer.rayMarchSegment=v
    return this;
  }
  get rayMarchSegment() {
    return this._rayMarchSegment;
  }
  set multiBounce(v) {
    this._multiBounce = v;
    this.gtaoComputer.multiBounce=v
    return this;
  }
  get multiBounce() {
    return this._multiBounce;
  }
  set blendColor(v) {
    this._blendColor = v;
    this.gtaoComputer.blendColor=v
    return this;
  }
  get blendColor() {
    return this._blendColor;
  }
  initPipeLine() {
    this.pipeLine = Engine.instance.device.createRenderPipeline({
      label: "gtao Pipline",
      layout:  `auto`,
      vertex: {
        module: Engine.instance.device.createShaderModule({
          code: gtao_vert,
        }),
        entryPoint: "main",
      },
      fragment: {
        module: Engine.instance.device.createShaderModule({
          code: gtao_frag,
        }),
        entryPoint: "main",
        targets: [
          {
            format: Engine.instance.format,
          },
        ],
      },
      primitive: {
        topology: "triangle-list",
        cullMode: "back",
        frontFace: "ccw",
      },
    });
  }
  initBindGroup() {
    const gtaoTexture=this.gtaoComputer.gtaoTexture;
    if(this.bindGroup&&this.bindGroup.id!=gtaoTexture.id){
      this.bindGroup=null;
    }
    if(!this.bindGroup){
      this.bindGroup=Engine.instance.device.createBindGroup({
        label: "Texture Group with Texture/Sampler",
        layout: this.pipeLine.getBindGroupLayout(0),
        entries: [
          {
            binding: 0,
            resource: this.sampler,
          },
          {
            binding: 1,
            resource: gtaoTexture.view,
          },
        ],
      });
      this.bindGroup.id=gtaoTexture.id;
    }
    return this.bindGroup
  }
  onRender(commandEncoder) {
    //执行帧渲染
    const pass = super.onRender(commandEncoder);
    const renderPass = commandEncoder.beginRenderPass(pass);
    renderPass.setPipeline(this.pipeLine);
    let bindGroup = this.initBindGroup();
    renderPass.setBindGroup(0, bindGroup);
    renderPass.draw(3);
    renderPass.end();
  }
  getDescript() {
    if (this._descript) {
      if (
        this._descript.size[0] !== Engine.instance.size[0] ||
        this._descript.size[1] !== Engine.instance.size[1]
      ) {
        this._descript = null;
      }else{
        this._descript.colorAttachments[0].view=Pass.instance().writeAttach.view;
    }
    }
    if (!this._descript) {
      this._descript = {
        colorAttachments: [
          {
            view: Pass.instance().writeAttach.view,
            loadOp: "clear",
            clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
            storeOp: "store",
          },
        ],
      };
      this._descript.size = Engine.instance.size;
    }
    return this._descript;
  }
}
export { GTAO };
